use clap::Parser;
use reqwest::Url;
use serde_json::Value;
// 定义 HTTPie 的 CLI 的主入口，它包含若干个子命令
// 下面 /// 的注释是文档，clap 会将其作为 CLI 的帮助

/// A simple httpie implementation with Rust
#[derive(Parser, Debug)]
#[command(
    version = "1.0",
    author = "Jim Da <dapengcheng2017@gmail.com>",
    about = "A simple httpie implementation with Rust"
)]
pub struct Opts {
    #[clap(subcommand)]
    pub subcmd: SubCommand,
}

// 子命令分别对应不同的 HTTP 方法，目前只支持 get / post
#[derive(Parser, Debug)]
pub enum SubCommand {
    ///send GET request
    Get {
        #[arg(help = "URL to request", value_parser = parse_input_url)]
        url: String,
        #[arg(short = 'H', long = "header", value_name = "KEY:VALUE")]
        headers: Vec<String>,
    },
    ///send GET request
    Post {
        #[arg(help = "URL to request", value_parser = parse_input_url)]
        url: String,
        #[arg(short = 'H', long = "header", value_name = "KEY:VALUE")]
        headers: Vec<String>,
        #[arg(help = "JSON body", value_parser = parse_input_json)]
        body: Option<String>,
    },
    // 我们暂且不支持其它 HTTP 方法
}

fn parse_input_url(input_url: &str) -> anyhow::Result<String> {
    input_url.parse::<Url>()?;
    Ok(input_url.into())
}

fn parse_input_json(input_json: &str) -> anyhow::Result<String> {
    serde_json::from_str::<Value>(input_json)
        .map(|_| input_json.into())
        .map_err(|e| anyhow::anyhow!("Invalid JSON format: {}", e))
}
